package searchurl.common;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import searchurl.model.SearchResult;

/**
 *
 * @author iridiumcao
 */
public class TextFileTools {

    /**
     * 判断文件的编码格式
     * @see http://blog.csdn.net/paul630/article/details/6164390 
     * 已知问题：对 UTF-8 without BOM 无法识别
     *
     * @param fileName
     * @return 文件编码格式
     * @throws Exception
     *
     */
    public static String getCodeString(String fileName) {
        String code = null;
        FileInputStream fis = null;
        BufferedInputStream bin = null;
        try {
            fis = new FileInputStream(fileName);
            bin = new BufferedInputStream(fis);
            int p = (bin.read() << 8) + bin.read();
            switch (p) {
                case 0xefbb:
                    code = "UTF-8";
                    break;
                case 0xfffe:
                    code = "Unicode";
                    break;
                case 0xfeff:
                    code = "UTF-16BE";
                    break;
                default:
                    code = "GBK";
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
                if (bin != null) {
                    bin.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return code;
    }

    /**
     * classy results as CMMC's requirements
     *
     * @param results
     * @deprecated
     * @return
     */
    public static String buildTextResult(List<SearchResult> results) {

        Map<String, Map<String, List<String>>> textResult = new HashMap<String, Map<String, List<String>>>();

        for (SearchResult sr : results) {
            String siteKey = sr.getSite();
            Map<String, List<String>> site = textResult.get(siteKey);
            if (site == null) {
                site = new HashMap<String, List<String>>();
                textResult.put(siteKey, site);
            }
            for (String keyword : sr.getKeywords()) {
                List<String> keywordList = site.get(keyword);
                if (keywordList == null) {
                    keywordList = new ArrayList<String>();
                    site.put(keyword, keywordList);
                }
                keywordList.add(sr.getUrl());
            }
        }

        StringBuilder sb = new StringBuilder();
        Set<String> siteKeys = textResult.keySet();
        for (String siteKey : siteKeys) {
            sb.append("=====").append(siteKey).append("====").append(SearchUrlContants.LINE_SEPARATOR);
            Map<String, List<String>> site = textResult.get(siteKey);
            Set<String> keywordMapKeys = site.keySet();
            for (String keyword : keywordMapKeys) {
                sb.append("\t\"").append(keyword).append("\"").append(SearchUrlContants.LINE_SEPARATOR);
                List<String> urls = site.get(keyword);
                for (String url : urls) {
                    sb.append("\t\t").append(url).append(SearchUrlContants.LINE_SEPARATOR);
                }
            }
            sb.append(SearchUrlContants.LINE_SEPARATOR);
        }
        return sb.toString();
    }

    /**
     *
     * @param results
     * @param prefilterFlag
     * @deprecated
     * @return
     */
    public static String buildTextResult(List<SearchResult> results, boolean prefilterFlag) {
        if (prefilterFlag) {
            //site - prefilter,prefilter -
            Map<String, Map<String, Map<String, List<String>>>> textResult = new HashMap<String, Map<String, Map<String, List<String>>>>();

            for (SearchResult sr : results) {
                String siteKey = sr.getSite();
                Map<String, Map<String, List<String>>> siteMap = textResult.get(siteKey);
                if (siteMap == null) {
                    siteMap = new HashMap<String, Map<String, List<String>>>();
                    textResult.put(siteKey, siteMap);
                }
                for (String prefilter : sr.getPrefilters()) {
                    Map<String, List<String>> prefilterMap = siteMap.get(prefilter);
                    if (prefilterMap == null) {
                        prefilterMap = new HashMap<String, List<String>>();
                        siteMap.put(prefilter, prefilterMap);
                    }

                    for (String keyword : sr.getKeywords()) {
                        List<String> keywordList = prefilterMap.get(keyword);
                        if (keywordList == null) {
                            keywordList = new ArrayList<String>();
                            prefilterMap.put(keyword, keywordList);
                        }
                        keywordList.add(sr.getUrl());
                    }
                }

            }

            StringBuilder sb = new StringBuilder();
            Set<String> siteKeys = textResult.keySet();
            for (String siteKey : siteKeys) {
                sb.append("=====").append(siteKey).append("====").append(SearchUrlContants.LINE_SEPARATOR);
                Map<String, Map<String, List<String>>> siteMap = textResult.get(siteKey);
                Set<String> keywordMapKeys = siteMap.keySet();
                for (String prefilter : keywordMapKeys) {
                    sb.append("\t\"").append(prefilter).append("\"").append(SearchUrlContants.LINE_SEPARATOR);
                    Map<String, List<String>> keywordsMap = siteMap.get(prefilter);
                    Set<String> keysOfKeywordsMap = keywordsMap.keySet();
                    for (String keyOfKeywordsMap : keysOfKeywordsMap) {
                        sb.append("\t\t\t\"").append(keyOfKeywordsMap).append("\"").append(SearchUrlContants.LINE_SEPARATOR);
                        List<String> urls = keywordsMap.get(keyOfKeywordsMap);
                        for (String url : urls) {
                            sb.append("\t\t\t\t").append(url).append(SearchUrlContants.LINE_SEPARATOR);
                        }
                    }
                }
                sb.append(SearchUrlContants.LINE_SEPARATOR);
            }
            return sb.toString();
        } else {
            return buildTextResult(results);
        }

    }

    public static boolean writeTextToFile(String text, File file) {
        boolean flag = false;
        try {
            if (file.exists() == false) {
                file.createNewFile();
            }
            FileOutputStream fos = new FileOutputStream(file);
            Writer out = new OutputStreamWriter(fos, "UTF-8");
            BufferedWriter bw = new BufferedWriter(out);
            bw.write(text);
            bw.flush();
            bw.close();
            out.close();
            fos.close();
            flag = true;
        } catch (IOException ioe) {
            ioe.printStackTrace();
            flag = false;
        }
        return flag;
    }

    public static Set<String> buildKeywordsFromPlainText(String keywordFilePath) {
        Set<String> keywords = new HashSet<String>();
        FileInputStream fis = null;
        InputStreamReader isr = null;
        BufferedReader bfr = null;
        try {
            String encoding = TextFileTools.getCodeString(keywordFilePath);
            fis = new FileInputStream(keywordFilePath);
            isr = new InputStreamReader(fis, encoding);
            bfr = new BufferedReader(isr);
            String line = bfr.readLine();
            while (line != null && !line.equals("")) {
                line = line.trim();
                String[] keywordsArray = line.split(",|，");
                for (String keyword : keywordsArray) {
                    keywords.add(keyword);
                }
                line = bfr.readLine();
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (bfr != null) {
                    bfr.close();
                }
                if (isr != null) {
                    isr.close();
                }
                if (fis != null) {
                    fis.close();
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return keywords;
    }

    public static String buildTextResultByUrl(List<SearchResult> results) {
        Map<String, Map<String, SearchResult>> textResult = new HashMap<String, Map<String, SearchResult>>();

        for (SearchResult sr : results) {
            String siteKey = sr.getSite();
            Map<String, SearchResult> siteMap = textResult.get(siteKey);
            if (siteMap == null) {
                siteMap = new HashMap<String, SearchResult>();
                textResult.put(siteKey, siteMap);
            }
            siteMap.put(sr.getUrl(), sr);
        }

        StringBuilder sb = new StringBuilder();
        Set<String> siteKeys = textResult.keySet();
        for (String siteKey : siteKeys) {
            sb.append("=====").append(siteKey).append("====").append(SearchUrlContants.LINE_SEPARATOR);
            Map<String, SearchResult> siteMap = textResult.get(siteKey);
            Set<String> siteMapKeys = siteMap.keySet();
            for (String key : siteMapKeys) {
                sb.append("\t\"").append(key).append("\"\t");
                SearchResult sr = siteMap.get(key);
                Set<String> prefilters = sr.getPrefilters();
                if (prefilters != null) {
                    for (String prefilter : sr.getPrefilters()) {
                        sb.append(prefilter).append(", ");
                    }
                    sb.append(",, ");
                }

                for (String keyword : sr.getKeywords()) {
                    sb.append(keyword).append(", ");
                }
                sb.append(SearchUrlContants.LINE_SEPARATOR);
            }
            sb.append(SearchUrlContants.LINE_SEPARATOR);
        }
        return sb.toString();
    }
}
